package com.xcw;

import javassist.*;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.Map;
import java.util.UUID;

public class DynamicCreateObject {

    public static Object getDynamicObject(Map map) throws Exception {

        //创建一个名称为Template的类
        Object template = addField("Template" + UUID.randomUUID(), map);

        return template;
    }

    public static Object addField(String className, Map fieldMap) throws Exception {

        // 获取javassist类池
        ClassPool pool = ClassPool.getDefault();

        // 创建javassist类
        CtClass ctClass = pool.makeClass(className, pool.get(Object.class.getName()));

        // 为创建的类ctClass添加属性
        Iterator iterator = fieldMap.entrySet().iterator();
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("return \"" + className + "{\" +\n");
        // 遍历所有的属性
        while (iterator.hasNext()) {
            Map.Entry entry = (Map.Entry) iterator.next();
            String fieldName = (String) entry.getKey();
            Object fieldValue = entry.getValue();
            // 增加属性，这里仅仅是增加属性字段
            String fieldType = fieldValue.getClass().getName();

            CtField ctField = new CtField(pool.get(fieldType), fieldName, ctClass);

            ctField.setModifiers(Modifier.PRIVATE);
            createSetterGetter(ctClass, ctField, fieldName);
            ctClass.addField(ctField);
            stringBuffer.append(createToString(fieldName) + "\",\"+\n");
        }
        String body = stringBuffer.substring(0,stringBuffer.length()-5) +"'}';";
        CtMethod toStringMethod = new CtMethod(pool.get("java.lang.String"), "toString", null, ctClass);
        toStringMethod.setBody(body);
        ctClass.addMethod(toStringMethod);

        // 为创建的javassist类转换为java类
        Class  c = ctClass.toClass();

        // 为创建java对象
        Object newObject = c.newInstance();

        iterator = fieldMap.entrySet().iterator();

        // 遍历所有的属性
        while (iterator.hasNext()) {

            Map.Entry entry = (Map.Entry) iterator.next();
            String fieldName = (String) entry.getKey();
            Object fieldValue =  entry.getValue();

            // 为属性赋值
            setFieldValue(newObject, fieldName, fieldValue);

        }
        return newObject;
    }

    public Object getFieldValue(Object object, String fieldName) throws Exception {

        Object result = null;
        // 获取对象的属性域
        Field fu = object.getClass().getDeclaredField(fieldName);
        // 设置对象属性域的访问属性
        fu.setAccessible(true);
        // 获取对象属性域的属性值
        result = fu.get(object);
        return result;

    }

    private static Object setFieldValue(Object object, String fieldName, Object val) throws Exception {

        Object result = null;
        Field fu = object.getClass().getDeclaredField(fieldName); // 获取对象的属性域
        // 设置对象属性域的访问属性
        fu.setAccessible(true);

        // 设置对象属性域的属性值
        fu.set(object, val);

        // 获取对象属性域的属性值
        result = fu.get(object);

        return result;
    }
    public static void createSetterGetter(CtClass ctClass, CtField field, String fieldName) throws CannotCompileException {
        String setter = "set" + fieldName.substring(0,1).toUpperCase()+fieldName.substring(1,fieldName.length());
        String getter = "get" + fieldName.substring(0,1).toUpperCase()+fieldName.substring(1,fieldName.length());
        ctClass.addMethod(CtNewMethod.setter(setter, field));
        ctClass.addMethod(CtNewMethod.getter(getter, field));

    }
    public static String createToString(String fieldName) throws CannotCompileException, NotFoundException {
        return         "                \" " +
                fieldName +
                "='\" + " +
                fieldName +
                " + '\\'' +\n";
    }
}